package com.xiyuan.smartutils.template.engine.expression.operator;

import java.util.ArrayList;

import com.xiyuan.smartutils.Types;

import com.xiyuan.smartutils.template.engine.ExpressionParser;
import com.xiyuan.smartutils.template.engine.VariableMap;
import com.xiyuan.smartutils.template.engine.exception.ExpressionException;
import com.xiyuan.smartutils.template.engine.expression.Expression;
import com.xiyuan.smartutils.template.engine.expression.symbol.Symbol;

/**
 * 括号运算()
 * 
 * @see _Method 括号操作符，和方法操作符不同的是内部是表达式，方法操作符括号内为参数
 * @author lgz 2020年12月7日 新建与整理
 */
public class _Parenthesis extends Operator
{
    private static final long serialVersionUID = 1L;
    private Expression claz;
    private ArrayList<Expression> eList; // 预编译的表达式列表
    
    public _Parenthesis(String path, int line, int column)
    {
        super(path, line, column);
        eList = new ArrayList<Expression>(0);
    }
    
    @Override
    public int getType()
    {
        return PARENTHESIS;
    }
    
    @Override
    public String toString()
    {
        
        StringBuilder strb = new StringBuilder("(");
        for (Expression ex : eList)
            strb.append(ex);
        
        strb.append(")");
        if(claz != null)
            strb.append(target);
        
        return strb.toString();
    }
    
    public void addExpression(Expression expression)
    {
        if (eList.size() == 0 && expression.getType() == Symbol.SYMBOL_COMMA)
            return;// 过滤第一个逗号
            
        eList.add(expression);
    }
    
    public ArrayList<Expression> getExpressionList()
    {
        return eList;
    }
    
    public int size()
    {
        return this.eList.size();
    }
    
    /** 括号运算 */
    public void parse() throws ExpressionException
    {
        // 左右括号去除
        ExpressionParser.parse_operators(eList);
        eList.trimToSize();
        if (this.size() > 0)
            this.setTarget(eList.get(0), true);
    }
    
    /** 添加类型强转 
     * @throws ExpressionException */
    public void convert(Expression obj) throws ExpressionException
    {
        if (this.size() != 1)
            throw new ExpressionException(this, "存在无法转型的表达式");
        
        this.claz = this.eList.get(0);
        this.setTarget(obj, true);
    }
    
    @Override
    protected Object build(VariableMap variableMap)
    {
        if (target == null)
            throw new ExpressionException(this,  "括号表达式存在无法处理的表达式");
        
        Object obj = target.execute(variableMap);
        if (claz == null)
            return obj;
        
        // 表示有类型强转
        Object clz = claz.execute(variableMap);
        if (clz == null || !(clz instanceof Class))
            throw new ExpressionException(this, "类型" + this + "返回结果不允许为null或者不是Class类型");
        
        Class<?> clzz = (Class<?>) clz;
        if (Types.isNumber(clzz))
        {// 数值类型
            if (obj == null || !Types.isNumber(obj) || obj instanceof Class)
                throw new ExpressionException(this, "类型转换失败，数值类型不支持转换" + obj);
            
            if (Types.isByte(clzz))
                return ((Number) obj).byteValue();
            
            if (Types.isShort(clzz))
                return ((Number) obj).shortValue();
            
            if (Types.isInt(clzz))
                return ((Number) obj).intValue();
            
            if (Types.isLong(clzz))
                return ((Number) obj).longValue();
            
            if (Types.isFloat(clzz))
                return ((Number) obj).floatValue();
            
            if (Types.isDouble(clzz))
                return ((Number) obj).doubleValue();
            
            throw new ExpressionException(this, "不支持的类型转换，数值类型仅支持 byte、short、int、long、float、double");
        }
        
        if (obj == null && Types.isPrimitive(clzz))
            throw new ExpressionException(this, "类型转换失败，原型数据转换不能为null");
        
        if (clzz == String.class && Types.isPrimitive(obj))
            return obj.toString();// string转换
            
        if ((obj instanceof Class) && !clzz.isAssignableFrom((Class<?>) obj))
            throw new ExpressionException(this, "类型转换失败，表达式结果{" + target + "}不是{" + claz + "}的子类");
        
        if (!clzz.isAssignableFrom(obj.getClass()))
            throw new ExpressionException(this, "类型转换失败，表达式结果{" + target + "}不是{" + claz + "}的子类");
        
        return obj;
        
    }

   
    
}
